home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / zmdm.zoo / zm.c < prev    next >
C/C++ Source or Header  |  1991-04-27  |  22KB  |  1,085 lines

  1. /*
  2.  *                ACKNOWLEDGEMENTS
  3.  *
  4.  *    ZMDM was derived from rz/sz for Unix  posted by 
  5.  *    Chuck Forsberg (...!tektronix!reed!omen!caf ). We
  6.  *    thank him for his excellent code, and for giving
  7.  *    us permission to use and distribute his code and
  8.  *    documentation.
  9.  *
  10.  *    Atari St version by:
  11.  *        Jwahar Bammi
  12.  * bang:   uunet!cadence!bammi
  13.  * domain: bammi@cadence.com
  14.  * GEnie:    J.Bammi
  15.  * CIS:    71515,155
  16.  */
  17.  
  18. /*
  19.  *   Z M . C
  20.  *    ZMODEM protocol primitives
  21.  *    05-24-89  Chuck Forsberg Omen Technology Inc
  22.  *
  23.  * Entry point Functions:
  24.  *    zsbhdr(type, hdr) send binary header
  25.  *    zshhdr(type, hdr) send hex header
  26.  *    zgethdr(hdr, eflag) receive header - binary or hex
  27.  *    zsdata(buf, len, frameend) send data
  28.  *    zrdata(buf, len) receive data
  29.  *    stohdr(pos) store position data in Txhdr
  30.  *    long rclhdr(hdr) recover position offset from header
  31.  *
  32.  *    This version implements ZMODEM Run Length Encoding, Comparision,
  33.  *    and variable length headers.  These features were not funded
  34.  *    by the original Telenet development contract.  This software,
  35.  *    including these features, may be freely used for non
  36.  *    commercial and educational purposes.  This software may also
  37.  *    be freely used to support file transfer operations to or from
  38.  *    licensed Omen Technology products.  Contact Omen Technology
  39.  *    for licensing for other uses.  Any programs which use part or
  40.  *    all of this software must be provided in source form with this
  41.  *    notice intact except by written permission from Omen
  42.  *    Technology Incorporated.
  43.  *
  44.  *        Omen Technology Inc        FAX: 503-621-3745
  45.  *        Post Office Box 4681
  46.  *        Portland OR 97208
  47.  *
  48.  *    Previous versions of this program (not containing the extensions
  49.  *    listed above) remain in the public domain.
  50.  *
  51.  *    This code is made available in the hope it will be useful,
  52.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  53.  *    DAMAGES OF ANY KIND.
  54.  *
  55.  */
  56. #include "config.h"
  57. #include "zmdm.h"
  58. #include "common.h"
  59.  
  60. #ifndef CANFDX
  61. #include "zmodem.h"
  62. #endif
  63.  
  64. #define xsendline(X) sendline(X)
  65.  
  66. static char *badcrc = "Bad CRC";
  67. static lastsent;    /* Last char we sent */
  68. static Not8bit;        /* Seven bits seen on header */
  69. static char *frametypes[] = {
  70.     "No Response to Error Correction Request",    /* -4 */
  71.     "Carrier Lost",        /* -3 */
  72.     "TIMEOUT",        /* -2 */
  73.     "ERROR",        /* -1 */
  74. #define FTOFFSET 3
  75.     "ZRQINIT",
  76.     "ZRINIT",
  77.     "ZSINIT",
  78.     "ZACK",
  79.     "ZFILE",
  80.     "ZSKIP",
  81.     "ZNAK",
  82.     "ZABORT",
  83.     "ZFIN",
  84.     "ZRPOS",
  85.     "ZDATA",
  86.     "ZEOF",
  87.     "ZFERR",
  88.     "ZCRC",
  89.     "ZCHALLENGE",
  90.     "ZCOMPL",
  91.     "ZCAN",
  92.     "ZFREECNT",
  93.     "ZCOMMAND",
  94.     "ZSTDERR",
  95.     "xxxxx"
  96. #define FRTYPES 22    /* Total number of frame types in this array */
  97.             /*  not including psuedo negative entries */
  98. };
  99.  
  100. #define flushmo flush_modem
  101.  
  102. /* Send ZMODEM binary header hdr of type type */
  103. void zsbhdr(len, type, hdr)
  104. int len, type;
  105. register char *hdr;
  106. {
  107.     register int n;
  108.     register unsigned short crc;
  109.  
  110. #ifndef DSZ
  111.     vfile2("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  112.       frametypes[type+FTOFFSET], rclhdr(hdr));
  113. #endif
  114.     if (type == ZDATA)
  115.         for (n = Znulls; --n >=0; )
  116.             xsendline(0);
  117.  
  118.     xsendline(ZPAD); xsendline(ZDLE);
  119.  
  120.     switch (Crc32t=Txfcs32) {
  121.     case 2:
  122.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  123.         flushmo();  break;
  124.     case 1:
  125.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  126.     default:
  127.         if (Usevhdrs) {
  128.             xsendline(ZVBIN);
  129.             zsendline(len);
  130.         }
  131.         else
  132.             xsendline(ZBIN);
  133.         zsendline(type);
  134.         crc = updcrc(type, 0);
  135.  
  136.         for (n=len; --n >= 0; ++hdr) {
  137.             zsendline(*hdr);
  138.             crc = updcrc((0377& *hdr), crc);
  139.         }
  140.         crc = updcrc(0,updcrc(0,crc));
  141.         zsendline(crc>>8);
  142.         zsendline(crc);
  143.     }
  144.     if (type != ZDATA)
  145.         flushmo();
  146. }
  147.  
  148. /* Send ZMODEM binary header hdr of type type */
  149. void zsbh32(len, hdr, type, flavour)
  150. int len, type, flavour;
  151. register char *hdr;
  152. {
  153.     register int n;
  154.     register unsigned long crc;
  155.  
  156.     xsendline(flavour); 
  157.     if (Usevhdrs) 
  158.         zsendline(len);
  159.     zsendline(type);
  160.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  161.  
  162.     for (n=len; --n >= 0; ++hdr) {
  163.         crc = UPDC32((0377 & *hdr), crc);
  164.         zsendline(*hdr);
  165.     }
  166.     crc = ~crc;
  167.     for (n=4; --n >= 0;) {
  168.         zsendline((unsigned int)crc);
  169.         crc >>= 8;
  170.     }
  171. }
  172.  
  173. /* Send ZMODEM HEX header hdr of type type */
  174. void zshhdr(len, type, hdr)
  175. int len, type;
  176. register char *hdr;
  177. {
  178.     register int n;
  179.     register unsigned int crc;
  180.  
  181. #ifndef DSZ
  182.     vfile2("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  183.       frametypes[type+FTOFFSET], rclhdr(hdr));
  184. #endif
  185.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  186.     if (Usevhdrs) {
  187.         sendline(ZVHEX);
  188.         zputhex(len);
  189.     }
  190.     else
  191.         sendline(ZHEX);
  192.     zputhex(type);
  193.     Crc32t = 0;
  194.  
  195.     crc = updcrc(type, 0);
  196.     for (n=len; --n >= 0; ++hdr) {
  197.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  198.     }
  199.     crc = updcrc(0,updcrc(0,crc));
  200.     zputhex(crc>>8); zputhex(crc);
  201.  
  202.     /* Make it printable on remote machine */
  203.     sendline(015); sendline(0212);
  204.     /*
  205.      * Uncork the remote in case a fake XOFF has stopped data flow
  206.      */
  207.     if (type != ZFIN && type != ZACK)
  208.         sendline(021);
  209.     flushmo();
  210. }
  211.  
  212. /*
  213.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  214.  */
  215. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  216.  
  217. void zsdata(buf, length, frameend)
  218. register char *buf;
  219. int length, frameend;
  220. {
  221.     register unsigned short crc;
  222.  
  223. #ifndef DSZ
  224.     vfile2("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  225. #endif
  226.     switch (Crc32t) {
  227.     case 1:
  228.         zsda32(buf, length, frameend);  break;
  229.     case 2:
  230.         zsdar32(buf, length, frameend);  break;
  231.     default:
  232.         crc = 0;
  233.         for (;--length >= 0; ++buf) {
  234.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  235.         }
  236.         xsendline(ZDLE); xsendline(frameend);
  237.         crc = updcrc(frameend, crc);
  238.  
  239.         crc = updcrc(0,updcrc(0,crc));
  240.         zsendline(crc>>8); zsendline(crc);
  241.     }
  242.     if (frameend == ZCRCW) {
  243.         xsendline(XON);  flushmo();
  244.     }
  245. }
  246.  
  247. void zsda32(buf, length, frameend)
  248. int length, frameend;
  249. register char *buf;
  250. {
  251.     register int c;
  252.     register unsigned long crc;
  253.  
  254.     crc = 0xFFFFFFFFL;
  255.     for (;--length >= 0; ++buf) {
  256.         c = *buf & 0377;
  257.         if (c & 0140)
  258.             xsendline(lastsent = c);
  259.         else
  260.             zsendline(c);
  261.         crc = UPDC32(c, crc);
  262.     }
  263.     xsendline(ZDLE); xsendline(frameend);
  264.     crc = UPDC32(frameend, crc);
  265.  
  266.     crc = ~crc;
  267.     for (c=4; --c >= 0;) {
  268.         zsendline((unsigned int)crc);  crc >>= 8;
  269.     }
  270. }
  271.  
  272. /*
  273.  * Receive array buf of max length with ending ZDLE sequence
  274.  *  and CRC.  Returns the ending character or error code.
  275.  *  NB: On errors may store length+1 bytes!
  276.  */
  277. int zrdata(buf, length)
  278. register char *buf;
  279. int length;
  280. {
  281.     register int c;
  282.     register unsigned short crc;
  283.     register char *end;
  284.     register int d;
  285.  
  286.     switch (Crc32r) {
  287.     case 1:
  288.         return zrdat32(buf, length);
  289.     case 2:
  290.         return zrdatr32(buf, length);
  291.     }
  292.  
  293.     crc = Rxcount = 0;  end = buf + length;
  294.     while (buf <= end) {
  295.         if ((c = zdlread()) & ~0377) {
  296. crcfoo:
  297.             switch (c) {
  298.             case GOTCRCE:
  299.             case GOTCRCG:
  300.             case GOTCRCQ:
  301.             case GOTCRCW:
  302.                 crc = updcrc((d=c)&0377, crc);
  303.                 if ((c = zdlread()) & ~0377)
  304.                     goto crcfoo;
  305.                 crc = updcrc(c, crc);
  306.                 if ((c = zdlread()) & ~0377)
  307.                     goto crcfoo;
  308.                 crc = updcrc(c, crc);
  309.                 if (crc & 0xFFFF) {
  310.                     log2(badcrc);
  311.                     return ERROR;
  312.                 }
  313.                 Rxcount = length - (end - buf);
  314. #ifndef DSZ
  315.                 vfile2("zrdata: %d  %s", Rxcount,
  316.                  Zendnames[d-GOTCRCE&3]);
  317. #endif
  318.                 return d;
  319.             case GOTCAN:
  320.                 log2("Sender Canceled");
  321.                 return ZCAN;
  322.             case TIMEOUT:
  323.                 log2("TIMEOUT");
  324.                 return c;
  325.             default:
  326.                 garbitch(); return c;
  327.             }
  328.         }
  329.         *buf++ = c;
  330.         crc = updcrc(c, crc);
  331.     }
  332. #ifdef DSZ
  333.     garbitch(); 
  334. #else
  335.     log2("Data subpacket too long");
  336. #endif
  337.     return ERROR;
  338. }
  339.  
  340. int zrdat32(buf, length)
  341. register char *buf;
  342. int length;
  343. {
  344.     register int c;
  345.     register unsigned long crc;
  346.     register char *end;
  347.     register int d;
  348.  
  349.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  350.     while (buf <= end) {
  351.         if ((c = zdlread()) & ~0377) {
  352. crcfoo:
  353.             switch (c) {
  354.             case GOTCRCE:
  355.             case GOTCRCG:
  356.             case GOTCRCQ:
  357.             case GOTCRCW:
  358.                 d = c;  c &= 0377;
  359.                 crc = UPDC32(c, crc);
  360.                 if ((c = zdlread()) & ~0377)
  361.                     goto crcfoo;
  362.                 crc = UPDC32(c, crc);
  363.                 if ((c = zdlread()) & ~0377)
  364.                     goto crcfoo;
  365.                 crc = UPDC32(c, crc);
  366.                 if ((c = zdlread()) & ~0377)
  367.                     goto crcfoo;
  368.                 crc = UPDC32(c, crc);
  369.                 if ((c = zdlread()) & ~0377)
  370.                     goto crcfoo;
  371.                 crc = UPDC32(c, crc);
  372.                 if (crc != 0xDEBB20E3L) {
  373.                     log2(badcrc);
  374.                     return ERROR;
  375.                 }
  376.                 Rxcount =